If you compacted the event processing into a single routine, a typical event loop would look something like the code in Example 6-12.
Xevent event; while (TRUE) { XNextEvent(dpy, &event); if (XFilterEvent(&event, None)) continue; DealWithEvent(&event); }
There are two new situations to deal with:
To tell the application what to pay attention to for a given event, XmbLookupString() returns a status value in a passed parameter, equal to one of the following:
XLookupKeysym | Indicates that the keysym should be checked. |
XLookupChars | Indicates that a string has been typed or composed. |
XLookupBoth | Means both of the above. |
XLookupNone | Means neither is ready for processing. |
XBufferOverflow | Means the supplied buffer is too small--call XmbLookupString() again with a bigger buffer |
XmbLookupString() also returns the length of the string in question. Note that XmbLookupString() returns the length of the string in bytes, while XwcLookupString() returns the length of the string in characters.
The example below should help show how these functions work. Most event processors perform a switch on the event type; assume you have done that and have received a KeyPress event.
case KeyPress: { Keysym keysym; Status status; int buflength; static int bufsize = 16; static char *buf = NULL; if (buf == NULL) { buf = malloc(bufsize); if (buf < 0) StopSequence(); } buflength = XmbLookupString(ic, &event, buf, bufsize, &keysym, &status); /* first, check to see if that worked */ if (status == XBufferOverflow) { buf = realloc(buf, (bufsize = buflength)); buflength = XmbLookupString(ic, &event, buf, bufsize, &keysym, &status); } /* We have a valid status. Check that */ switch(status) { case XLookupKeysym: DealWithKeysym(keysym); break; case XLookupBoth: DealWithKeysym(keysym); /* **FALL INTO** charcter case */ case XLookupChars: DealWithString(buf, buflength); case XLookupNone: break; } /* end switch(status) */ } /* end case KeyPress segment */ break; /* we are in a switch(event.type) statement */